﻿using Sasa.QualityTools.CodeAnalysis.Core.Models;
using Sasa.QualityTools.CodeAnalysis.FxCopIntegrator.Properties;
using System;
using System.Collections.Generic;
using System.Linq;
using Sasa.QualityTools.CodeAnalysis.Common;

namespace Sasa.QualityTools.CodeAnalysis.FxCopIntegrator.ViewModels
{
    public class CodeMetricsCalculatorViewModel : CodeAnalyzerViewModelBase<CodeMetricsCalculator>
    {
        private MetricsErrorCodes errorCode;


        public ICollection<MetricValueViewModel> MetricValues { get; private set; }

        public ICodeAnalysisResultValueFilter Filter
        {
            get
            {
                return Model.Report.Filter;
            }
            set
            {
                Model.Report.Filter = value;
            }
        }


        public CodeMetricsCalculatorViewModel()
        {
            MetricValues = new List<MetricValueViewModel>();
        }


        protected override void PerformCodeAnalysisCore()
        {
            errorCode = Model.PerformCodeAnalysis();

            foreach (var value in Model.Report.MetricValues)
            {
                MetricValues.Add(new MetricValueViewModel(value));
            }
        }

        protected override void LoadCodeAnalysisReportCore()
        {
            Model.LoadCodeAnalysisReport();

            foreach (var value in Model.Report.MetricValues)
            {
                MetricValues.Add(new MetricValueViewModel(value));
            }
        }

        protected override void NotifyCodeAnalysisPerformed()
        {
            Message = "Calculating Code Metrics...";
            Status = CodeAnalysisStatus.Analyzing;
        }

        protected override void NotifyCodeAnalysisCompleted()
        {
            var messages = new List<string>();

            if (errorCode == MetricsErrorCodes.None)
            {
                Status = CodeAnalysisStatus.Completed;
                var metricValue = MetricValues.First(o => o.Kind == "Module");
                messages.Add(Text.Format("Code metrics calculation completed (Maintainability Index = {0}).", metricValue.MaintainabilityIndex));
            }
            else
            {
                Status = CodeAnalysisStatus.Warning;
                messages.Add("");
                messages.Add("Warning :");
                messages.AddRange(GetMetricsErrorMessages(errorCode));
            }

            Message = String.Join(Environment.NewLine, messages);
        }

        protected override void NotifyCodeAnalysisFailed(Exception ex)
        {
            Message = ex.Message;
            Status = CodeAnalysisStatus.Failed;
        }

        private IEnumerable<string> GetMetricsErrorMessages(MetricsErrorCodes errorCode)
        {
            var messages = new List<string>();

            if (errorCode.HasFlag(MetricsErrorCodes.AnalysisError))
            {
                messages.Add(Resources.MetricsFailedBecauseOfAnalysisError);
            }
            if (errorCode.HasFlag(MetricsErrorCodes.TargetLoadError))
            {
                messages.Add(Resources.MetricsFailedBecauseOfTargetLoadError);
            }
            if (errorCode.HasFlag(MetricsErrorCodes.OutputError))
            {
                messages.Add(Resources.MetricsFailedBecauseOfOutputError);
            }
            if (errorCode.HasFlag(MetricsErrorCodes.CommandLineSwitchError))
            {
                messages.Add(Resources.MetricsFailedBecauseOfCommandLineSwitchError);
            }
            if (errorCode.HasFlag(MetricsErrorCodes.AssemblyReferencesError))
            {
                messages.Add(Resources.MetricsFailedBecauseOfAssemblyReferencesError);
            }
            if (errorCode.HasFlag(MetricsErrorCodes.UnknownError))
            {
                messages.Add(Resources.MetricsFailedBecauseOfUnknownError);
            }

            return messages;
        }
    }
}
